package cn.xmirror.sca.ui.window;

import cn.xmirror.sca.common.OpenSCASettingState;
import cn.xmirror.sca.common.constant.ExploitLevelEnum;
import cn.xmirror.sca.common.dto.Vulnerability;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.components.JBTextArea;
import com.intellij.uiDesigner.core.GridConstraints;
import icons.Icons;

import javax.swing.*;
import java.text.SimpleDateFormat;
import java.util.*;

public class DescriptionVulnerabilityPanel extends JPanel {

    private Vulnerability vulnerability;

    public DescriptionVulnerabilityPanel(Vulnerability vulnerability) {
        super(PaintUtils.defaultMarginGridLayoutManager(10, 1));
        this.vulnerability = vulnerability;
        add(getTitlePanel(), PaintUtils.panelGridConstraints(0));
        add(getDescriptionPanel(), PaintUtils.panelGridConstraints(1));
        add(getSuggestionPanel(), PaintUtils.panelGridConstraints(2));
        add(PaintUtils.moreInfoPanel(), PaintUtils.panelGridConstraints(9));
    }

    private JPanel getTitlePanel() {
        JPanel panel = PaintUtils.defaultGridPanel(3, 1);
        JLabel titleLabel = new JLabel();
        titleLabel.setFont(PaintUtils.primaryTitleFont());
        titleLabel.setText(vulnerability.getName());
        titleLabel.setIcon(Icons.getIconFromResources(vulnerability.getSecurityLevelId(), Icons.IconSize.SIZE24));

        panel.add(titleLabel, MyGridConstraints.gridBuilder(0).build());
        panel.add(vulnerabilityNumberPanel(), MyGridConstraints.gridBuilder(1).build());
        panel.add(simpleDataPanel(), MyGridConstraints.gridBuilder(2).build());
        return panel;
    }

    private JPanel vulnerabilityNumberPanel() {
        String cweId = vulnerability.getCweId();
        String cveId = vulnerability.getCveId();
        String cnnvdId = vulnerability.getCnnvdId();
        String cnvdId = vulnerability.getCnvdId();
        String xmirrorId = vulnerability.getId();
        List<String> cwes = processCwe(cweId);
        int columnCount = (cwes.size() > 0 ? cwes.size() * 2 - 1 : 0) +    // cweId with `|`
                (cveId != null ? 2 : 0) +    // cveId with `|`
                (cnnvdId != null ? 2 : 0) +  // cnnvdId with `|`
                (cnvdId != null ? 2 : 0) +
                (xmirrorId != null ? 2 : 0);
        JPanel panel = PaintUtils.defaultGridPanel(1, columnCount);

        int lastColumn = PaintUtils.addRowOfItemsToPanel(panel, -1, cwes, false,
                item -> "https://cwe.mitre.org/data/definitions/" + item.substring(4) + ".html");

        lastColumn = PaintUtils.addRowOfItemsToPanel(panel, lastColumn, emptyOrSingleList(cveId),
                item -> "https://cve.mitre.org/cgi-bin/cvename.cgi?name=" + item);

        lastColumn = PaintUtils.addRowOfItemsToPanel(panel, lastColumn, emptyOrSingleList(cnnvdId),
                item -> "http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=" + item);

        lastColumn = PaintUtils.addRowOfItemsToPanel(panel, lastColumn, emptyOrSingleList(cnvdId),
                item -> "https://www.cnvd.org.cn/flaw/show/" + item);

        // xmirrorId定位到sca主页
        PaintUtils.addRowOfItemsToPanel(panel, lastColumn, emptyOrSingleList(xmirrorId),
                item -> OpenSCASettingState.getInstance().getOpenSCASetting().getServerAddress());
        return panel;
    }

    private List<String> emptyOrSingleList(String item) {
        return StringUtil.isNotEmpty(item) ? Collections.singletonList(item) : Collections.emptyList();
    }

    private List<String> processCwe(String cweStr) {
        if (StringUtil.isNotEmpty(cweStr)) {
            String[] cwes = cweStr.split(",");
            return Arrays.asList(cwes);
        }
        return new ArrayList<>();
    }


    private JPanel simpleDataPanel() {
        JPanel panel = PaintUtils.defaultGridPanel(1, 5);
        String releaseTag = "发布日期：";
        Date releaseDate = vulnerability.getReleaseDate();
        String exploitTag = "利用难度：";
        int exploitId = vulnerability.getExploitLevelId();
        int columnCount = PaintUtils.addRowOfItemsToPanel(panel, -1, releaseTag, false, null);
        columnCount = PaintUtils.addRowOfItemsToPanel(panel, columnCount,  releaseDate != null ? new SimpleDateFormat("yyyy-MM-dd").format(releaseDate) : "-", false, null);
        columnCount = PaintUtils.addRowOfItemsToPanel(panel, columnCount, exploitTag, null);
        PaintUtils.addRowOfItemsToPanel(panel, columnCount, ExploitLevelEnum.getTag(exploitId), false, null);
        return panel;
    }

    private JPanel getDescriptionPanel() {
        JPanel panel = PaintUtils.defaultGridPanel(2, 1);

        JLabel descriptionHeader = new JLabel("漏洞描述");
        descriptionHeader.setFont(PaintUtils.secondaryTitleFont());
        descriptionHeader.setIcon(Icons.VUL_DESCRIPTION);
        String descriptionText = vulnerability.getDescription();
        if (!StringUtil.isNotEmpty(descriptionText)) {
            descriptionText = vulnerability.getDescriptionEn();
        }
        if (!StringUtil.isNotEmpty(descriptionText)) {
            descriptionText = "暂无漏洞描述";
        }
        descriptionText = descriptionText.trim();
        JBTextArea description = new JBTextArea(descriptionText);
        description.setEditable(false);
        description.setLineWrap(true);
        description.setOpaque(false);
        JScrollPane scrollPane = PaintUtils.wrapWithScrollPanel(description);
        scrollPane.setOpaque(false);
        scrollPane.getViewport().setOpaque(false);

        panel.add(descriptionHeader, MyGridConstraints.gridBuilder(0).build());
        panel.add(scrollPane, MyGridConstraints.gridBuilder(1).setFill(GridConstraints.FILL_BOTH).build());
        return panel;
    }

    private JPanel getSuggestionPanel() {
        JPanel panel = PaintUtils.defaultGridPanel(2, 1);
        JLabel suggestionHeader = new JLabel("修复建议");
        suggestionHeader.setFont(PaintUtils.secondaryTitleFont());
        suggestionHeader.setIcon(Icons.FIX_SUGGESTION);

        String suggestionText = vulnerability.getSuggestion();
        if (StringUtil.isNotEmpty(suggestionText)) {
            suggestionText = suggestionText.trim();
        } else {
            suggestionText = "暂无修复建议";
        }

        JTextArea suggestion = new JTextArea(suggestionText);
        suggestion.setLineWrap(true);
        suggestion.setEditable(false);
        suggestion.setOpaque(false);
        suggestion.setBorder(null);
        JScrollPane scrollPane = PaintUtils.wrapWithScrollPanel(suggestion);
        scrollPane.setOpaque(false);
        scrollPane.getViewport().setOpaque(false);

        panel.add(suggestionHeader, MyGridConstraints.gridBuilder(0).build());
        panel.add(scrollPane, MyGridConstraints.gridBuilder(1).setFill(GridConstraints.FILL_BOTH).build());
        return panel;
    }
}
